﻿using Collections.Pooled;
using CSRedis;
using DotNetCommon.Encrypt;
using DotNetCommon.Extensions;
using furion.blog.Application.Contracts;
using furion.blog.Application.CustomMapper;
using furion.blog.Domain.IRepositories;
using furion.blog.Domain.MySQL;
using furion.blog.Domain.Query.User;
using furion.blog.Domain.Shared;
using furion.blog.Domain.Shared.Dto.User;
using furion.blog.Domain.Shared.Enum;
using furion.blog.Domain.Shared.Vo.Menu;
using furion.blog.Domain.Shared.Vo.User;
using furion.blog.Utils;
using Furion;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using JWT.Algorithms;
using JWT.Builder;
using Mapster;
using MapsterMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace furion.blog.Application
{
    public class UserService : IUserService, ISingleton
    {
        private const string DEFAULT_PASSWORD = "888888";

        private readonly IUserRepository _userRepository;
        private readonly IMenuRepository _menuRepository;
        private readonly CSRedisClient[] _csredis;
        private readonly UserMapper _userMapper;
        private readonly MenuMapper _menuMapper;
        private readonly IRoleService _roleService;

        public UserService(
            IUserRepository userRepository,
            IMenuRepository menuRepository,
            CSRedisClient[] csredis,
            UserMapper userMapper,
            MenuMapper menuMapper,
            IRoleService roleService
            )
        {
            this._userRepository = userRepository;
            this._menuRepository = menuRepository;
            this._csredis = csredis;
            this._userMapper = userMapper;
            this._menuMapper = menuMapper;
            this._roleService = roleService;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<UserLoginSuccessVO> Login(UserLoginDto dto)
        {
            string captcha = await this._csredis[15].GetAsync<string>(dto.Token);
            if (string.IsNullOrEmpty(captcha))
            {
                throw Oops.Oh("验证码已过期，请刷新");
            }
            if (captcha.ToLower() != dto.Captcha.ToLower())
            {
                throw Oops.Oh("验证码有误");
            }
            User user = await _userRepository.FindByUsername(dto.Username);
            if (user == null)
            {
                throw Oops.Oh("账号有误");
            }
            if (user.Password != DESEncrypt.Encrypt(dto.Password, App.Configuration["SecretKey"]))
            {
                throw Oops.Oh("密码有误");
            }
            //登录成功
            var token = JwtUtil.CreateToken(new Dictionary<string, object> {
                //隐藏信息
                { "id",user.UserId.ToString()},
                { "role","User"}
            });
            return new UserLoginSuccessVO { Username = user.UserName, Token = token };
        }


        /// <summary>
        /// 当前登录账号信息
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<CurrentLoginUserInfoVO> CurrentLoginUserInfo(long userId)
        {
            User user = await this._userRepository.FindByUserId(userId);
            if (user == null)
            {
                throw Oops.Oh("账号不存在");
            }

            return new CurrentLoginUserInfoVO
            {
                Name = user.UserName,
                NickName = user.NickName,
                RealName = user.RealName,
                Avatar = user.Avatar,
                Roles = new PooledList<string>().ToList<string>()
            };
        }

        /// <summary>
        /// 当前账号拥有菜单
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<List<DashboardMenuVO>> CurrentUserMenus(long userId)
        {
            User user = await this._userRepository.FindByUserId(userId);
            if (user == null)
            {
                throw Oops.Oh("账号不存在");
            }
            if (user.IsSuperAdmin == YesOrNoEnum.Yes.ToString())
            {
                //超级管理员拥有的菜单 
                return await SuperAdminMenus();
            }
            else
            {
                //其他账号拥有的菜单
            }
            return null;
        }

        /// <summary>
        /// 超级管理员拥有的菜单
        /// </summary>
        /// <returns></returns>
        private async Task<List<DashboardMenuVO>> SuperAdminMenus()
        {
            List<Menu> list = await this._menuRepository.All();
            if (!list.IsNullOrEmpty())
            {
                PooledList<DashboardMenuVO> mList = new PooledList<DashboardMenuVO>();
                list.ForEach(m =>
                {
                    try
                    {
                        var o = this._menuMapper.Map<Menu, DashboardMenuVO>(m);
                        mList.Add(o);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }

                });

                return mList.FetchToTree(i => i.Id, i => i.Pid, i => i.Children, i => i.Pid == null || i.Pid == 0L);
            }
            else
            {
                return DefaultMenus().FetchToTree(i => i.Id, i => i.Pid, i => i.Children, i => i.Pid == null || i.Pid == 0L);
            }
        }


        /// <summary>
        /// 默认菜单
        /// </summary>
        /// <returns></returns>
        private PooledList<DashboardMenuVO> DefaultMenus()
        {
            PooledList<DashboardMenuVO> list = new PooledList<DashboardMenuVO>();

            list.Add(new DashboardMenuVO
            {
                Id = 1L,
                Name = "系统设置",
                Pid = 0L,
                Children = null,
                Hidden = false,
                Key = "system_setting",
                Path = "/system_setting",
                Icon = "AppleOutlined",
                Redirect = "/system_setting/menu/async/index",
                Component = "BasicLayout",
                /*Extra = new Dictionary<string, object> {
                  { "path","/system_setting"},{ "component","BasicLayout"},{ "key","system_setting"},{ "redirect", "/system_setting/menu/async/index"},
                  { "pid", 0L},{ "hidden", false},{ "keepAlive", false},{ "icon", "AppleOutlined"}
              }*/
            });

            list.Add(
                new DashboardMenuVO
                {
                    Id = 11L,
                    Name = "同步菜单",
                    Pid = 1L,
                    Children = null,
                    Hidden = false,
                    Key = "system_setting_menu_async",
                    Path = "/system_setting/menu/async/index",
                    Icon = "SwapOutlined",
                    Redirect = "",
                    Component = "/system_setting/menu/async/index",
                    /*Extra = new Dictionary<string, object> {
                        { "path", "/system_setting/menu/async/index"},{ "component", "/system_setting/menu/async/index"},{ "key", "system_setting_menu_async"},
                        { "pid", 1L},{ "hidden", false},{ "keepAlive", false},{ "icon", "SwapOutlined"}
              }*/
                });

            return list;
        }

        /// <summary>
        /// 账号档案
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<UserProfileVO> Profile(long userId)
        {
            User user = await this._userRepository.FindByUserId(userId);
            if (user == null)
            {
                throw Oops.Oh("账号不存在");
            }
            return user.Adapt<UserProfileVO>();
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task ChangePassword(UserChangePasswordDto dto)
        {
            if (dto.NewPassword != dto.ConfirmPassword)
            {
                throw Oops.Oh("新密码与确认密码不一致");
            }
            User user = await this._userRepository.FindByUserId(dto.UserId);
            if (user == null)
            {
                throw Oops.Oh("账号不存在");
            }
            if (user.Password != DESEncrypt.Encrypt(dto.OldPassword, App.Configuration["SecretKey"]) ) {
                throw Oops.Oh("旧密码有误");
            }
            user.Password = DESEncrypt.Encrypt(dto.NewPassword, App.Configuration["SecretKey"]);
            await this._userRepository.Update(user);
        }


        /// <summary>
        /// 更新账号档案
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task UpdateProfile(UserProfileUpdateDto dto)
        {
            User user = await this._userRepository.FindByUserId(dto.UserId);
            if (user == null)
            {
                throw Oops.Oh("账号不存在");
            }
            user = this._userMapper.Map(dto, user);
            await this._userRepository.Update(user);
        }


        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public async Task<PageVO> List(UserListQuery query)
        {
            return await this._userRepository.List(query);
        }

        /// <summary>
        /// 修改状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task ChangeStatus(long id, string status, long userId)
        {
            User user = await this._userRepository.FindByUserId(id);
            if (user == null)
            {
                throw Oops.Oh("信息不存在");
            }
            if (user.IsSuperAdmin == YesOrNoEnum.Yes.ToString())
            {
                throw Oops.Oh("超级管理员状态无法修改");
            }
            user.Status = status;
            user.UpdatedBy = userId;
            user.UpdatedTime = DateTime.Now;
            await this._userRepository.Update(user);
        }

        /// <summary>
        /// 删除账号
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task Delete(long id, long userId) {
            User user = await this._userRepository.FindByUserId(id);
            if (user == null)
            {
                throw Oops.Oh("信息不存在");
            }
            if (user.IsSuperAdmin == YesOrNoEnum.Yes.ToString())
            {
                throw Oops.Oh("超级管理员无法删除");
            }
            user.IsDelete = YesOrNoEnum.Yes.ToString();
            user.UpdatedBy = userId;
            user.UpdatedTime = DateTime.Now;
            await this._userRepository.Update(user);
        }

        /// <summary>
        /// 恢复原始密码
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userId">操作人id</param>
        /// <returns></returns>
        public async Task PasswordRecover(long id, long userId) {
            User user = await this._userRepository.FindByUserId(id);
            if (user == null)
            {
                throw Oops.Oh("信息不存在");
            }
            user.Password = DESEncrypt.Encrypt(MD5Encrypt.MD5(DEFAULT_PASSWORD), App.Configuration["SecretKey"]);
            user.UpdatedBy = userId;
            user.UpdatedTime = DateTime.Now;
            await this._userRepository.Update(user);
        }


        /// <summary>
        /// 账号详细信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<UserDetailVO> Detail(long id) {
            User user = await this._userRepository.FindByUserId(id);
            if (user == null) {
                return null;
            }
            UserDetailVO vo = user.Adapt<UserDetailVO>();
            if (vo.RoleId != null) {
                var role = await this._roleService.Detail((long)vo.RoleId);
                vo.RoleName = role == null ? string.Empty : role.RoleName;
            }
            return vo;
        }


        /// <summary>
        /// 新增账号
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task Add(UserCreateDto dto) {
            User user = await this._userRepository.FindByUsername(dto.UserName);
            if (user != null) {
                throw Oops.Oh("账号已存在");
            }
            user = dto.Adapt<User>();
            user.UserId = IdUtil.Id();
            await this._userRepository.Save(user);
        }


        /// <summary>
        /// 更新账号信息
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task Update(UserUpdateDto dto) {
            User user = await this._userRepository.First(new UserDetailQuery { UserIdNE = dto.UserId , UserName = dto.UserName }.Exp());
            if (user != null) {
                throw Oops.Oh("账号已存在");
            }
            user = await this._userRepository.FindByUserId((long)dto.UserId);
            if (user == null) {
                throw Oops.Oh("信息不存在");
            }
            user = this._userMapper.Map(dto,user);
            await this._userRepository.Update(user);
        }


        /// <summary>
        /// 统计
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public async Task<long> Count(UserDetailQuery query) {
            return await this._userRepository.Count(query.Exp());
        }


    }
}
